package com.aliyun.heiyu.powermaster.server.service;

import com.aliyun.heiyu.common.util.StringUtil;
import com.aliyun.heiyu.powermaster.proto.*;
import com.aliyun.heiyu.powermaster.server.Error;
import com.aliyun.heiyu.powermaster.server.annotation.Transactional;
import com.aliyun.heiyu.powermaster.server.dao.StrategyDao;
import com.aliyun.heiyu.powermaster.server.dao.entity.DeviceCommonEntity;
import com.aliyun.heiyu.powermaster.server.dao.entity.Strategy2DeviceEntity;
import com.aliyun.heiyu.powermaster.server.dao.impl.StrategyImpl;
import com.aliyun.heiyu.powermaster.server.manager.DeviceManagerImpl;
import com.aliyun.heiyu.powermaster.server.manager.StrategyManager;
import com.aliyun.heiyu.powermaster.server.manager.StrategyManagerInterface;
import com.aliyun.heiyu.powermaster.server.strategy.StrategyContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;

public class StrategyServiceImpl implements StrategyService {
    private static Logger logger = LoggerFactory.getLogger(StrategyServiceImpl.class);

    private StrategyManagerInterface strategyManager;
    private StrategyDao strategyDao;
    private StrategyContext strategyContext;

    public StrategyServiceImpl() {
        strategyManager = StrategyManager.getInstance();
        strategyDao = new StrategyImpl();
        strategyContext = new StrategyContext();
    }

    /**
     * 新增策略
     * @param request
     * @return
     */
    public BaseReply addStrategy(AddStrategyRequest request) {
        BaseReply.Builder builder = BaseReply.newBuilder();
        String errMsg = insertVerity(request);
        if (errMsg != null) {
            builder.setErrCode(Error.FAILED.getCode()).setErrMsg(errMsg);
            return builder.build();
        }
        addStrategy1(request);
        builder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage());
        return builder.build();
    }

    /**
     * 更新策略
     * @param request
     * @return
     */
    public BaseReply updateStrategy(AddStrategyRequest request) {
        BaseReply.Builder builder = BaseReply.newBuilder();
        String errMsg = updateVerify(request.getId());
        if (errMsg != null) {
            builder.setErrCode(Error.FAILED.getCode()).setErrMsg(errMsg);
            return builder.build();
        }
        updateStrategy1(request);
        builder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage());
        return builder.build();
    }

    /**
     * 批量移除策略
     * @param
     */
    public BaseReply removeStrategy(RemoveStrategyRequest request){
        BaseReply.Builder builder = BaseReply.newBuilder();
        String ids = request.getIds();
        try{
            removeStrategy1(ids);
            builder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage());
        } catch (Exception e){
            builder.setErrCode(Error.FAILED.getCode()).setErrMsg(Error.FAILED.getMessage());
        }
        return builder.build();
    }

    /**
     * 获取策略详情列表
     * @param request name,type
     * @return
     */
    public GetStrategiesReply getStrategies(GetStrategiesRequest request){
        GetStrategiesReply.Builder builder = GetStrategiesReply.newBuilder();
        builder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage());
        GetStrategiesReply.Data.Builder builder1 = GetStrategiesReply.Data.newBuilder();
        String str = request.getStr();
        String type = request.getType();
        int count = strategyManager.getCountByCondition(str, type);
        if(count == 0){
            builder.setData(builder1);
            return builder.build();
        }
        int pageSize = request.getPageSize();
        int pageNum = request.getPageNum();
        List<StrategyDetail> list = null;
        if(pageSize == -1){
            list = strategyManager.getByCondition(str, type);
        } else {
            if(pageNum <= 0){
                pageNum = 1;
            }
            if(pageSize <= 0){
                pageSize = 10;
            }
            int start = (pageNum - 1) * pageSize;
            list = strategyManager.getByCondition(str, type, start, pageSize);
        }
        builder1.setCurrentPage(pageNum).setTotal(count);
        builder1.addAllStrategies(list);
        builder.setData(builder1);
        return builder.build();
    }

    /**
     * 根据策略ID获取策略详情
     * @param strategyID
     * @return
     */
    public StrategyDetail getStrategyDetail(int strategyID) {
        StrategyDetail strategyDetail = strategyManager.getStrategy(strategyID);
        return strategyDetail;
    }

    /**
     * 更新某策略中的设备，如果其他策略中也包括同一台设备，那么将其他策略中的这台设备删除： 保证一台设备对应一个策略
     */
    @Transactional
    public BaseReply updateDevicesInStrategy(AddDeviceInStrategyRequest request) {
        BaseReply.Builder builder = BaseReply.newBuilder();
        //验证参数
        int strategyID = request.getId();
        String errMsg = updateVerify(strategyID);
        if (errMsg != null) {
            builder.setErrCode(Error.FAILED.getCode()).setErrMsg(errMsg);
            return builder.build();
        }

        builder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage());
        boolean updated = true;
        //deviceInfos && 删除其他策略中包含的设备
        List<EquipmentNumber> equipmentNumbersList = request.getEquipmentNumbersList();
        Object[] deviceInfos = equipmentNumbersList.stream().map(o -> o.getNumber()).toArray();
        //把这个策略下的所有设备和已经有策略的设备都删除掉
        updated &= strategyManager.deleteStrategyDevices(strategyID,deviceInfos);
        if (!updated) {
            throw new RuntimeException("update strategy " + strategyID + " failed!");
        }
        //新增设备
        for (Object s : deviceInfos){
            Strategy2DeviceEntity entity = new Strategy2DeviceEntity();
            entity.setStrategyID(strategyID);
            entity.setDeviceID(String.valueOf(s));
            updated &= strategyManager.insertDevice(entity);
            if (!updated) {
                throw new RuntimeException("update strategy " + strategyID + " failed!");
            }
        }
        return builder.build();
    }

    /**
     * 从策略下批量移除设备
     * @param request
     */
    @Transactional
    public BaseReply removeDeviceInStrategy(RemoveDeviceInStrategyRequest request) {
        BaseReply.Builder builder = BaseReply.newBuilder();
        //验证参数
        int strategyID = request.getId();
        String errMsg = updateVerify(strategyID);
        if (errMsg != null) {
            builder.setErrCode(Error.FAILED.getCode()).setErrMsg(errMsg);
            return builder.build();
        }

        builder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage());
        List<String> numbers = Arrays.asList(request.getDeviceNumbers().split(","));
        boolean updated = strategyManager.deleteDevices(strategyID, numbers.toArray());
        if (!updated) {
            throw new RuntimeException("update strategy " + strategyID + " failed!");
        }
        return builder.build();
    }

    /**
     * 根据条件获取策略控制历史
     * @return
     */
    public GetStrategyControlHistoryReply getStrategyControlHistory(GetStrategyControlHistoryRequest request){
        GetStrategyControlHistoryReply.Builder builder = GetStrategyControlHistoryReply.newBuilder();
        builder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage());
        GetStrategyControlHistoryReply.Data.Builder builder1 = GetStrategyControlHistoryReply.Data.newBuilder();
        DeviceInfo.Builder deviceBuilder = DeviceInfo.newBuilder();
        String deviceId = request.getDeviceId();
        deviceBuilder.setEquipmentNumber(deviceId);
        DeviceManagerImpl instance = DeviceManagerImpl.getInstance();
        DeviceCommonEntity oneDeviceCommon = instance.findOneDeviceCommon(deviceId);
        if(oneDeviceCommon != null){
            deviceBuilder.setDeviceType(StringUtil.nullFilter(oneDeviceCommon.getType()));
        } else {
            return builder.setErrCode(Error.FAILED.getCode()).setErrMsg("设备不存在，请重试").setData(builder1).build();
        }
        builder1.setDeviceInfo(deviceBuilder.build());
        int count = strategyManager.getCountHistoryByCondition(deviceId);
        if(count == 0){
            builder.setData(builder1);
            return builder.build();
        }
        int pageSize = request.getPageSize();
        int pageNum = request.getPageNum();
        List<StrategyControlHistory> list = null;
        if(pageSize == -1){
            list = strategyManager.getHistoryByCondition(deviceId);
        } else {
            if(pageNum <= 0){
                pageNum = 1;
            }
            if(pageSize <= 0){
                pageSize = 10;
            }
            int start = (pageNum - 1) * pageSize;
            list = strategyManager.getHistoryByCondition(deviceId, start, pageSize);
        }
        builder1.addAllStrategyControlHistories(list);
        builder1.setCurrentPage(pageNum);
        builder1.setTotal(count);
        builder.setData(builder1);
        return builder.build();
    }

    @Override
    public GetStrategyControlSurveyReply.Data getStrategyControlSurvey() {
        DeviceManagerImpl instance = DeviceManagerImpl.getInstance();
        List<StrategyDetail> list = strategyManager.getAllStrategiesOfOn();
        int aiControlNum = 0;
        int diyControlNum = 0;
        int noneControlNum = 0;
        int level0Num = 0;
        int level1Num = 0;
        int level2Num = 0;
        int level3Num = 0;
        int busyDeviceNum = 0;
        int freeDeviceNum = 0;
        for (StrategyDetail strategy : list) {
            int type = strategy.getType();
            String controlLevel = strategy.getControlLevel();
            int count = strategy.getDeviceInfosCount();
            if (type == 1) {
                aiControlNum += count;
                if ("0".equals(controlLevel)) {
                    level0Num += count;
                } else if ("1".equals(controlLevel)) {
                    level1Num += count;
                } else if ("2".equals(controlLevel)) {
                    level2Num += count;
                } else if ("3".equals(controlLevel)) {
                    level3Num += count;
                }
            } else if (type == 2) {
                diyControlNum += count;
            }
        }
        int total = instance.totalServerAmount();
        busyDeviceNum = instance.usedServerAmount();
        freeDeviceNum = total - busyDeviceNum;
        freeDeviceNum = freeDeviceNum < 0 ? 0 : freeDeviceNum;
        noneControlNum = total - aiControlNum - diyControlNum;
        noneControlNum = noneControlNum < 0 ? 0 : noneControlNum;
        GetStrategyControlSurveyReply.Data.Builder builder1 = GetStrategyControlSurveyReply.Data.newBuilder();
        builder1.setAiControlNum(aiControlNum).setDiyControlNum(diyControlNum)
            .setNoneControlNum(noneControlNum).setControlLevel0Num(level0Num)
            .setControlLevel1Num(level1Num).setControlLevel2Num(level2Num)
            .setControlLevel3Num(level3Num).setBusyDeviceNum(busyDeviceNum)
            .setFreeDeviceNum(freeDeviceNum);
        return builder1.build();
    }

    private StrategyDetail addRequestToStrategyDetail(AddStrategyRequest request){
        StrategyDetail.Builder builder = StrategyDetail.newBuilder();
        builder.setStrategyName(request.getStrategyName());
        builder.setSwitchOn(request.getSwitchOn());
        builder.addAllStrategyActions(request.getStrategyActionsList());
        builder.setBusiness(request.getBusiness());
        builder.setControlLevel(request.getControlLevel());
        builder.setType(request.getType());
        builder.setStrategyID(request.getId());
        return builder.build();
    }

    @Transactional
    private void addStrategy1(AddStrategyRequest request) {
        boolean inserted = strategyManager.insert(addRequestToStrategyDetail(request));
        if (!inserted) {
            throw new RuntimeException("insert strategy " + request.getStrategyName() + " failed!");
        }
    }

    @Transactional
    private void updateStrategy1(AddStrategyRequest request) {
        //update strategy
        boolean updated = strategyManager.patch(addRequestToStrategyDetail(request));
        if (!updated) {
            throw new RuntimeException("update strategy " + request.getId() + " failed!");
        }
    }

    @Transactional
    private void removeStrategy1(String ids) {
        String[] strategyIDs = ids.split(",");
        boolean deleted = strategyManager.delete(strategyIDs);
        if (!deleted) {
            throw new RuntimeException("delete strategy failed!");
        }
    }

    private String insertVerity(AddStrategyRequest request){
        String errMsg = null;
        String strategyName = request.getStrategyName();
        if(StringUtil.isEmpty(strategyName)){
            errMsg = "策略名称不能为空";
            return errMsg;
        }
        //策略名称不重复校验
        boolean b = strategyManager.virtyStrategyNameExit(strategyName);
        if(b){
            errMsg = "策略名称已经存在";
            return errMsg;
        }
        return null;
    }

    private String updateVerify(int id) {
        String errMsg = null;
        boolean b = strategyManager.virtyStrategyIdExit(id);
        //策略ID校验
        if(!b){
            errMsg = "该策略ID不存在";
        }
        return errMsg;
    }

    /**
     * 检测要增加的设备是否已存在其他策略中
     */
    public List<String> updateDevicesInStrategyCheck(AddDeviceInStrategyCheckRequest request) {
        //条件检测
        List<String> conflictDeviceIds = new ArrayList<>();
        if (request.getDeviceIds() == null || "".equals(request.getDeviceIds())) {
            return conflictDeviceIds;
        }
        int strategyId = request.getId();
        //开始冲突检测工作
        List<String> deviceIds = Arrays.asList(request.getDeviceIds().split(","));
        for (String deviceId : deviceIds) {
            Strategy2DeviceEntity byDeviceId = strategyManager.findByDeviceId(deviceId);
            if (byDeviceId != null && !conflictDeviceIds.contains(deviceId) && request.getId() != byDeviceId.getStrategyID()){
                conflictDeviceIds.add(deviceId);
            }

        }
        return conflictDeviceIds;
    }

}
